﻿using System;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace SpeechSynthesizerBeeDriver
{
    public class Syn6288
    {
        public const int HEADLEN = 5;
        private byte pi;
        private SerialPort _serial;
        private bool _isBusy = false;

        private byte[] head = { 0xfd, 0x00, 0x00, 0x01, 0x00 }; //合成播放命令
        private byte[] sound = { 0xfd, 0x00, 0x00, 0x01, 0x01 }; //合成提示音
        private byte[] boud = { 0xFD, 0x00, 0x03, 0x31, 0x00 }; //设置波特率

        public Syn6288(string com)
        {
            // write your code here
            _serial = new SerialPort(com,9600,Parity.None,8,StopBits.One);
            _serial.Open();
            _serial.DataReceived += new SerialDataReceivedEventHandler(_serial_DataReceived);
            _serial.ErrorReceived += new SerialErrorReceivedEventHandler(_serial_ErrorReceived);
        }

        void _serial_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            Debug.Print("_serial_ErrorReceived---"+e.EventType.ToString());
        }

        void _serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] bytes = new byte[1];

            // as long as there is data waiting to be read
            while (_serial.BytesToRead > 0)
            {
                // read a single byte
                _serial.Read(bytes, 0, bytes.Length);
                // send the same byte back
                switch (bytes[0])
                {
                    case 0x4A:
                        Debug.Print("芯片初始化成功");
                        break;
                    case 0x41:
                        Debug.Print("命令正确且接收成功");
                        break;
                    case 0x45:
                        Debug.Print("命令错误,接收失败");
                        break;
                    case 0x4E:
                        _isBusy = true;
                        Debug.Print("正在播音");
                        break;
                    case 0x4F:
                        _isBusy = false;
                        Debug.Print("空闲");
                        break;
                }
            }
        }

        /// <summary>
        /// /*发送文本合成命令，*/
        /// </summary>
        /// <param name="text"></param>
        /// <param name="textlen">文本长度,不能大于200</param>
        /// <param name="music">music为背景音乐设置</param>
        /// <param name="encode">编码格式0:GB2312,1:GBK,2:BIG5,3:UNICODE</param>
        public void Play(byte[] text, byte textlen, byte music,byte encode=1)
        {
            pi = 0;
            Thread.Sleep(100);
            head[2] = (byte) (textlen + 3);
            switch (music)
            {
                case 0:
                    head[4] = 0x00;
                    break;
                case 1:
                    head[4] = 0x08;
                    break;
                case 2:
                    head[4] = 0x10;
                    break;
                case 3:
                    head[4] = 0x18;
                    break;
                case 4:
                    head[4] = 0x20;
                    break;
                case 5:
                    head[4] = 0x28;
                    break;
                case 6:
                    head[4] = 0x30;
                    break;
                case 7:
                    head[4] = 0x38;
                    break;
                case 8:
                    head[4] = 0x40;
                    break;
                case 9:
                    head[4] = 0x48;
                    break;
                case 10:
                    head[4] = 0x50;
                    break;
                case 11:
                    head[4] = 0x58;
                    break;
                case 12:
                    head[4] = 0x60;
                    break;
                case 13:
                    head[4] = 0x68;
                    break;
                case 14:
                    head[4] = 0x70;
                    break;
                case 15:
                    head[4] = 0x78;
                    break;
            }

            head[4] += encode;

            for (int i = 0; i < 5; i++)
            {
                pi ^= head[i];
                _serial.WriteByte(head[i]);
                Thread.Sleep(2);
            }
            for (int j = 0; j < textlen; j++)
            {
                pi ^= text[j];
                _serial.WriteByte(text[j]);
                Thread.Sleep(2);
            }
            _serial.WriteByte(pi);
            Thread.Sleep(300);
        }


        /// <summary>
        /// 波特率设置
        /// </summary>
        /// <param name="boudr"></param>
        public void Slaveboudset(ushort boudr)
        {
            byte p = 0;
            switch (boudr)
            {
                case 9600:
                    boud[4] = 0x00;
                    break;
                case 19200:
                    boud[4] = 0x01;
                    break;
                //case 38400: // 不稳定,详见芯片资料
                //    boud[4] = 0x02;
                //    break;
            }
            for (int z = 0; z < HEADLEN; z++)
            {
                p ^= boud[z];
                _serial.WriteByte(boud[z]);
                Thread.Sleep(2);
            }
            _serial.WriteByte(p);
            p = 0;
            for (int z = 0; z < HEADLEN; z++)
            {
                p ^= boud[z];
                _serial.WriteByte(boud[z]);
                Thread.Sleep(2);
            }
            _serial.WriteByte(p);
            Thread.Sleep(200);
            _serial.BaudRate = boudr;
        }

        public void Stop()
        {
            SendCmd(Cmd.Stop);
        }

        public void Resume()
        {
            SendCmd(Cmd.Resune);
        }

        public bool IsBusy()
        {
            SendCmd(Cmd.Status);
            Thread.Sleep(50);
            return _isBusy;
        }

        public void Pause()
        {
            SendCmd(Cmd.Pause);
        }

        public void Sleep()
        {
            SendCmd(Cmd.PowerDown);
        }

        private void SendCmd(Cmd cmd)
        {
            byte p = 0;
            byte[] boud = { 0xFD, 0x00, 0x02, (byte)cmd};
            for (int z = 0; z < boud.Length; z++)
            {
                p ^= boud[z];
                _serial.WriteByte(boud[z]);
                Thread.Sleep(2);
            }
            _serial.WriteByte(p);
            Thread.Sleep(200);
        }
    }

    public enum Cmd:byte
    {
        Stop =0x02,
        Pause = 0x03,
        Resune = 0x04,
        Status = 0x21,
        PowerDown=0x88,
    }
}
